142. 环形链表 II

142. 环形链表 II

题目

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

进阶:

你是否可以使用 O(1) 空间解决此题?

示例 1:

1
2
3
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

1
2
3
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

1
2
3
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

题解

题解原文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next


class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 1. 使用快慢指针在链表中找相遇的点
# 2. 找到相遇的点后 index1 从链表头开始,index2 从相遇点开始,分别以步长1往下走,二者相遇的点则为环形链表的入口
fast, slow = head, head
# 快指针一直往下走
while fast and fast.next:
# 慢指针一次走一步
slow = slow.next
# 快指针一次走两步
fast = fast.next.next
if slow == fast:
# 快慢指针相遇,说明是个环形链表
# index1 从链表头开始
index1 = head
# index2 从相遇点开始
index2 = slow
while index1 != index2:
# index1 和 index2 每次都走一步
index1 = index1.next
index2 = index2.next
# index1 和 index2 的相遇点就是环形链表的入口
return index1
return None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type ListNode struct {
Val int
Next *ListNode
}

func detectCycle(head *ListNode) *ListNode {
fast, slow := head, head
for fast!=nil && fast.Next!=nil{
slow = slow.Next
fast = fast.Next.Next

if slow == fast{
index1 := head
index2 := slow

for index1 != index2{
index1 = index1.Next
index2 = index2.Next
}
return index1
}
}
return nil
}

变体

总结

参考